#include "PrivacyListManager.h"


PrivacyListManager::PrivacyListManager(XMPPConnection * connection) :
	connection(connection)
{
	packetFilter = new AndFilter(new IQTypeFilter(IQ::Type::SET),
    		new PacketExtensionFilter("query", "jabber:iq:privacy"));
}


std::string PrivacyListManager::getUser() {
	return connection->getUser();
}


void PrivacyListManager::init() {
    // Register the new instance and associate it with the connection 
    instances.put(connection, this);
    // Add a listener to the connection that removes the registered instance when
    // the connection is closed
	connection->addConnectionListener(new RmPLManagerListener()); 
	connection->addPacketListener(new PrivacyListPacketListener(), packetFilter);
}


PrivacyListManager * getInstanceFor(XMPPConnection * connection) {
	return instances.get(connection);
}


Privacy * getRequest(Privacy * requestPrivacy) {
	// The request is a get iq type
	requestPrivacy->setType(Privacy::Type::GET);
	requestPrivacy->setFrom(getUser());
		
	// Filter packets looking for an answer from the server.
	PacketFilter * responseFilter = new PacketIDFilter(requestPrivacy->getPacketID());
    PacketCollector * response = connection->createPacketCollector(responseFilter);
        
    // Send create & join packet.
    connection->sendPacket(requestPrivacy);
        
    // Wait up to a certain number of seconds for a reply.
    Privacy * privacyAnswer = (Privacy*) response->nextResult(SmackConfiguration::getPacketReplyTimeout());
        
    // Stop queuing results
    response.cancel();

    // Interprete the result and answer the privacy only if it is valid
    if (privacyAnswer == NULL) {
		return NULL;
    } else if (privacyAnswer.getError() != null) {
	}
    return privacyAnswer;
}


Packet * setRequest(Privacy * requestPrivacy) {
		
	// The request is a get iq type
	requestPrivacy->setType(Privacy::Type::SET);
	requestPrivacy->setFrom(getUser());
	
	// Filter packets looking for an answer from the server.
	PacketFilter * responseFilter = new PacketIDFilter(requestPrivacy->getPacketID());
    PacketCollector * response = connection->createPacketCollector(responseFilter);
        
    // Send create & join packet.
    connection->sendPacket(requestPrivacy);
        
    // Wait up to a certain number of seconds for a reply.
    Packet * privacyAnswer = response->nextResult(SmackConfiguration::getPacketReplyTimeout());
        
    // Stop queuing results
    response->cancel();

    // Interprete the result and answer the privacy only if it is valid
    if (privacyAnswer == NULL) {
    } else if (privacyAnswer->getError() != NULL) {
    }
    return privacyAnswer;
}


Privacy * getPrivacyWithListNames() {
		
	// The request of the list is an empty privacy message
	Privacy * request = new Privacy();
		
	// Send the package to the server and get the answer
	return getRequest(request);
}


PrivacyList * getActiveList() {
    Privacy * privacyAnswer = getPrivacyWithListNames();
	std::string listName = privacyAnswer->getActiveName();
    bool isDefaultAndActive = !(privacyAnswer->getActiveName().empty()) 
		&& !(privacyAnswer->getDefaultName().empty()) 
		&& privacyAnswer->getActiveName() == privacyAnswer->getDefaultName();
    return new PrivacyList(true, isDefaultAndActive, listName, getPrivacyListItems(listName));
}


PrivacyList * getDefaultList() {
    Privacy * privacyAnswer = getPrivacyWithListNames();
	std::string listName = privacyAnswer->getDefaultName();
    bool isDefaultAndActive = !(privacyAnswer->getActiveName().empty()) 
		&& !(privacyAnswer->getDefaultName().empty())
        && privacyAnswer->getActiveName() == privacyAnswer->getDefaultName();
    return new PrivacyList(isDefaultAndActive, true, listName, getPrivacyListItems(listName));
}


std::vector<PrivacyItem*> getPrivacyListItems(std::string & listName) {
        
    // The request of the list is an privacy message with an empty list
    Privacy * request = new Privacy();
    request->setPrivacyList(listName, std::vector<PrivacyItem*>);
        
    // Send the package to the server and get the answer
    Privacy * privacyAnswer = getRequest(request);
        
    return privacyAnswer->getPrivacyList(listName);
}


PrivacyList * getPrivacyList(std::string & listName) {
	return new PrivacyList(false, false, listName, getPrivacyListItems(listName));
}


PrivacyList[] getPrivacyLists() {
    Privacy * privacyAnswer = getPrivacyWithListNames();
	std::vector<std::string> names = privacyAnswer->getPrivacyListNames();
    PrivacyList[] lists = new PrivacyList[names.size()];
    bool isActiveList;
    bool isDefaultList;
    int index=0;
	for(std::vector<std::string>::iterator it = names.begin();
			it != names.end(); ++it) {
		isActiveList = *it == privacyAnswer->getActiveName();
        isDefaultList = *it == privacyAnswer->getDefaultName();
        lists[index] = PrivacyList(isActiveList, isDefaultList,
				listName, getPrivacyListItems(*it));
        ++index;
    }
    return lists;
}


void setActiveListName(std::string & listName) {

	// The request of the list is an privacy message with an empty list
	Privacy * request = new Privacy();
	request->setActiveName(listName);

	// Send the package to the server
	setRequest(request);
}


void declineActiveList() {
		
	// The request of the list is an privacy message with an empty list
	Privacy * request = new Privacy();
	request->setDeclineActiveList(true);

	// Send the package to the server
	setRequest(request);
}


void setDefaultListName(std::string & listName) {

	// The request of the list is an privacy message with an empty list
	Privacy * request = new Privacy();
	request->setDefaultName(listName);

	// Send the package to the server
	setRequest(request);
}


void declineDefaultList() {

	// The request of the list is an privacy message with an empty list
	Privacy * request = new Privacy();
	request->setDeclineDefaultList(true);

	// Send the package to the server
	setRequest(request);
}


void createPrivacyList(std::string & listName, std::list<PrivacyItem*> & privacyItems) {

	updatePrivacyList(listName, privacyItems);
}


void updatePrivacyList(std::string & listName, std::list<PrivacyItem*> & privacyItems) {

	// Build the privacy package to add or update the new list
	Privacy * request = new Privacy();
	request->setPrivacyList(listName, privacyItems);

	// Send the package to the server
	setRequest(request);
}


void deletePrivacyList(std::string & listName) {

	// The request of the list is an privacy message with an empty list
	Privacy * request = new Privacy();
	std::vector<PrivacyItem*> listItem;
	request->setPrivacyList(listName, listItem);

	// Send the package to the server
	setRequest(request);
}


void addListener(PrivacyListListener * listener) {
	// Keep track of the listener so that we can manually deliver extra
	// messages to it later if needed.
	//TODO synchronized (listeners) {

	listeners.add(listener);

	//}
}    

